<template>
    <div :class="containerClasses" :style="containerStyles" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave"
        @click="onClick" @focus="onFocus" @blur="onBlur">
        <slot />
    </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'

/**
 * 微交互动画组件
 * @description 提供按钮、表单等元素的交互反馈动画
 */

interface Props {
    // 交互类型
    type?: 'button' | 'input' | 'card' | 'link' | 'icon'
    // 动画效果
    effect?: 'hover' | 'click' | 'focus' | 'ripple' | 'all'
    // 动画时长
    duration?: 'fast' | 'normal' | 'slow'
    // 是否禁用
    disabled?: boolean
    // 自定义类名
    customClass?: string
    // 涟漪效果颜色
    rippleColor?: string
    // 是否启用涟漪效果
    enableRipple?: boolean
}

const props = withDefaults(defineProps<Props>(), {
    type: 'button',
    effect: 'all',
    duration: 'normal',
    disabled: false,
    customClass: '',
    rippleColor: 'rgba(255, 255, 255, 0.3)',
    enableRipple: true
})

const emit = defineEmits<{
    'interaction-start': [type: string]
    'interaction-end': [type: string]
    'click': [event: MouseEvent]
}>()

// 交互状态
const isHovered = ref(false)
const isFocused = ref(false)
const isPressed = ref(false)

// 计算容器类名
const containerClasses = computed(() => {
    const classes = ['micro-interaction', `micro-${props.type}`]

    if (props.customClass) {
        classes.push(props.customClass)
    }

    if (isHovered.value) {
        classes.push('is-hovered')
    }

    if (isFocused.value) {
        classes.push('is-focused')
    }

    if (isPressed.value) {
        classes.push('is-pressed')
    }

    if (props.disabled) {
        classes.push('is-disabled')
    }

    return classes.join(' ')
})

// 计算容器样式
const containerStyles = computed(() => {
    const styles: Record<string, string> = {}

    if (props.disabled) {
        styles['pointer-events'] = 'none'
        styles['opacity'] = '0.6'
    }

    return styles
})

// 获取动画时长
const getDuration = () => {
    switch (props.duration) {
        case 'fast': return 150
        case 'slow': return 500
        default: return 300
    }
}

// 鼠标进入事件
const onMouseEnter = () => {
    if (props.disabled) return

    isHovered.value = true
    emit('interaction-start', 'hover')
}

// 鼠标离开事件
const onMouseLeave = () => {
    if (props.disabled) return

    isHovered.value = false
    emit('interaction-end', 'hover')
}

// 点击事件
const onClick = (event: MouseEvent) => {
    if (props.disabled) return

    isPressed.value = true
    emit('interaction-start', 'click')
    emit('click', event)

    // 创建涟漪效果
    if (props.enableRipple && props.effect.includes('ripple')) {
        createRipple(event)
    }

    // 重置按下状态
    setTimeout(() => {
        isPressed.value = false
        emit('interaction-end', 'click')
    }, getDuration())
}

// 焦点事件
const onFocus = () => {
    if (props.disabled) return

    isFocused.value = true
    emit('interaction-start', 'focus')
}

// 失焦事件
const onBlur = () => {
    if (props.disabled) return

    isFocused.value = false
    emit('interaction-end', 'focus')
}

// 创建涟漪效果
const createRipple = (event: MouseEvent) => {
    const element = event.currentTarget as HTMLElement
    const rect = element.getBoundingClientRect()
    const size = Math.max(rect.width, rect.height)
    const x = event.clientX - rect.left - size / 2
    const y = event.clientY - rect.top - size / 2

    const ripple = document.createElement('span')
    ripple.className = 'ripple-effect'
    ripple.style.cssText = `
    position: absolute;
    width: ${size}px;
    height: ${size}px;
    left: ${x}px;
    top: ${y}px;
    background: ${props.rippleColor};
    border-radius: 50%;
    transform: scale(0);
    animation: ripple ${getDuration()}ms ease-out;
    pointer-events: none;
  `

    element.appendChild(ripple)

    // 动画结束后移除涟漪元素
    setTimeout(() => {
        if (ripple.parentNode) {
            ripple.parentNode.removeChild(ripple)
        }
    }, getDuration())
}
</script>

<style scoped lang="scss">
@use '../assets/styles/components/_animations' as *;
</style>